/*
Author: Aaron Lumaksana
Version: 1.1
Date: 8/08/2010

Release Note:
1.1 : 
	*fixed delay bug (foobar2000.exe maintains stream when paused.. changed condition to overcome this)
	*console displays process name using audio other than foobar (mainly for debugging of random  pauses)
	*hide console
	*added this note.
	
1.0 :
	*first release
*/

#include <iostream>
#include <audiopolicy.h>
#include <mmdeviceapi.h>
#include <string>
#include <Psapi.h>
#include <Windows.h>

using namespace std;




template < class T >

//release pointers when no longer needed.**** not sure if delete p is needed *****
void SafeRelease( T* p )
{
    if (p)
    {
		//cout<<p<<endl;
        p->Release();
        p = NULL;
		delete p;
		//cout<<p<<endl;
    }
}


/*Most of the code below is from
cboard.cprogramming.com/windows-programming/88433-check-running-process-dev-cplusplus.html
*/

bool isRunning(string pName)
{
	unsigned long aProcesses[1024], cbNeeded, cProcesses;
	if(!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
		return false;

	cProcesses = cbNeeded / sizeof(unsigned long);
	for(unsigned int i = 0; i < cProcesses; i++)
	{
		if(aProcesses[i] == 0)
			continue;

		HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, aProcesses[i]);
		char buffer[50];
		GetModuleBaseNameA(hProcess, 0, buffer, 50);
		CloseHandle(hProcess);
		if(pName == string(buffer))
			return true;
	}
	return false;
}

// gets processname from the process ID
string GetProcessNameFromPId(DWORD *pid)
{
	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, *pid);
	char buffer[50];
	GetModuleBaseNameA(hProcess, 0, buffer, 50);
	CloseHandle(hProcess);
	return string(buffer);
}

// Gets Number of processes using audio

int GetNumberOfProcess()
{
	IMMDeviceEnumerator* deviceEnumerator = NULL;
	IMMDevice* device = NULL;
	IAudioSessionManager2* sessionManager = NULL;
	IAudioSessionEnumerator* sessionEnumerator = NULL;
	IAudioSessionControl* session = NULL;
	IAudioSessionControl2* session2 = NULL;

	unsigned long pId = 0;
	int numberOfProcesses = 0;
	int numberOfActiveProcesses = 0 ;

	AudioSessionState state;

	//create device enumerator
	
	CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&deviceEnumerator);
	// get default device
	deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device);
	//CHECK_HR( hr =device->GetId(&deviceId));
	// activate session manager
	device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**)&sessionManager);
	// make enum
	sessionManager->GetSessionEnumerator(&sessionEnumerator);
	// get number of active and inactive processes
	sessionEnumerator ->GetCount(&numberOfProcesses);

	//count number of active processes and get the name of the process other than foobar2000
	for (int i = 0; i < numberOfProcesses; i++)
	{
		sessionEnumerator->GetSession(i, &session);
		session->GetState(&state);
		if (state == 1)
		{
			session->QueryInterface(__uuidof(IAudioSessionControl2), (void**) &session2);
			session2->GetProcessId(&pId);
			if(GetProcessNameFromPId(&pId) != "foobar2000.exe")
			{
				cout<<GetProcessNameFromPId(&pId)<<endl;
			}
			numberOfActiveProcesses++;
			SafeRelease(session2);
		}
		SafeRelease(session);
	}


	//CLEANUP

	SafeRelease(deviceEnumerator);
	SafeRelease(device);
	SafeRelease(sessionEnumerator);
	SafeRelease(sessionManager);
	
	//debug
	//cout<<"number of active processes"<<numberOfActiveProcesses<<endl;
	return numberOfActiveProcesses;
	

}

void play()
{
	keybd_event(VK_CONTROL, 0,0,0);
	keybd_event(VK_MENU, 0,0,0);
	keybd_event(0x50, 0,0,0); //p
	Sleep(100);
	keybd_event(VK_CONTROL, 0,KEYEVENTF_KEYUP,0);
	keybd_event(VK_MENU, 0,KEYEVENTF_KEYUP,0);
	keybd_event(0x50, 0,KEYEVENTF_KEYUP,0); //p
}

void pause()
{
	keybd_event(VK_CONTROL, 0,0,0);
	keybd_event(VK_MENU, 0,0,0);
	keybd_event(0x53, 0,0,0); //s
	Sleep(100);
	keybd_event(VK_CONTROL, 0,KEYEVENTF_KEYUP,0);
	keybd_event(VK_MENU, 0,KEYEVENTF_KEYUP,0);
	keybd_event(0x53, 0,KEYEVENTF_KEYUP,0); //s
}

int main()
{
	FreeConsole();
	bool playing = false;
	LPVOID reserved = NULL;
	CoInitializeEx(reserved, COINIT_APARTMENTTHREADED);
	while(true)
	{
		if (true)
		{

			if ((GetNumberOfProcess() > 1) && playing)
			{
				cout<<"pause!!!"<<endl;
				pause();
				playing = false;
			}
			else if ((GetNumberOfProcess() <=1) && !playing)
			{
				cout<<"PLAY!!!"<<endl;
				play();
				playing = true;
			}
		}
		Sleep(1000);
		
		
	}
	CoUninitialize();
	return 0;
}
